#include "JoinGame.hh"
#include "Done.hh"
#include "PlayerJoined.hh"
#include "XmlServerThread.cc"
#include "../World/Galaxy.hh"
#include "../World/Player.hh"
using namespace Network;
using namespace World;

spJoinGame JoinGame::construct(QDomElement const& message) {
    QDomElement name = message.firstChildElement("name");

    if (name.isNull())
        throw NonFatalProtocolError("init.join_game.name missing");

    QDomNode nameText = name.firstChild();

    if (!nameText.isText())
        throw NonFatalProtocolError("init.join_game.name invalid");

    return spJoinGame(new JoinGame(nameText.toText().nodeValue()));
}

JoinGame::JoinGame(QString const& name):
    name(name) {}

void JoinGame::process_on_server(XmlServerThread& thread) {
    if (thread.get_state() != AUTH_OK)
        throw NonFatalProtocolError("init.join_game unexpected");

    try {
        spUser user = thread.get_user();
        spGalaxy galaxy = Galaxy::select(name);
        spPlayer player;
        PlayerMapByUser others;
        bool newPlayer = galaxy->join(user, player, others);
        thread.set_player(player);
        thread.set_state(GAME);
        Done const done(true, "init.join_game ok");
        done.send_to(*thread.get_socket());

        // Az új játékos értesítése a régi játékosokról.
        for (
          PlayerMapByUser::iterator i = others.begin();
          i != others.end();
          ++i
        ) {
            PlayerJoined playerJoined(i.value()->get_user()->get_name());
            playerJoined.send_to(*thread.get_socket());
        }

        if (newPlayer) {
            // A többi játékos értesítése az új játékos csatlakozásáról.
            PlayerJoined playerJoined(player->get_user()->get_name());

            for (
              PlayerMapByUser::const_iterator i = others.begin();
              i != others.end();
              ++i
            ) {
                pXmlServerThread serverThread =
                  XmlServerThread::select(i.value());

                if (serverThread)
                    playerJoined.send_to(*serverThread->get_socket());
            }
        }
    } catch (GalaxyNotFoundException& ex) {
        Done const done(false, "init.join_game failed not found");
        done.send_to(*thread.get_socket());
    } catch (GalaxyFullException& ex) {
        Done const done(false, "init.join_game failed full");
        done.send_to(*thread.get_socket());
    } catch (GameStartedException& ex) {
        Done const done(false, "init.join_game failed already started");
        done.send_to(*thread.get_socket());
    }
}

QDomDocument JoinGame::to_xml() const {
    QDomDocument doc;
    QDomElement init = doc.createElement("init");
    QDomElement joinGame = doc.createElement("join_game");
    QDomElement nameElem = doc.createElement("name");
    QDomText nameText = doc.createTextNode(name);
    doc.appendChild(init);
    init.appendChild(joinGame);
    joinGame.appendChild(nameElem);
    nameElem.appendChild(nameText);
    return doc;
}
